package com.uzai.console.service.reportpanel;

import cn.hutool.core.date.DateTime;
import cn.hutool.extra.cglib.CglibUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.uzai.common.exception.BusinessException;
import com.uzai.console.common.utils.DateUtil;
import com.uzai.console.dto.remoteapi.DataPanelRemoteQuery;
import com.uzai.console.dto.reportpanel.DataPanelOptDto;
import com.uzai.console.entity.Device;
import com.uzai.console.entity.DeviceGroup;
import com.uzai.console.entity.ReportPanel;
import com.uzai.console.enums.ReportPanelTypeEnum;
import com.uzai.console.mapper.DataPanelMapper;
import com.uzai.console.mapper.DeviceGroupMapper;
import com.uzai.console.service.device.DeviceService;
import com.uzai.console.vo.device.DeviceInfoVo;
import com.uzai.console.vo.reportpanel.DataPanelVo;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * The type Base data panel service.
 * <p>
 * x * @author mingyang.chen create in 2023/3/29 11:29
 */
public abstract class BaseDataPanelService implements DataPanelService {

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private DeviceGroupMapper deviceGroupMapper;

    @Autowired
    private DataPanelMapper dataPanelMapper;

    /**
     * 转换
     *
     * @param reportPanel the report panel
     * @return t t
     */
    public DataPanelVo convert(ReportPanel reportPanel) {

        DataPanelVo result = CglibUtil.copy(reportPanel, childDataPanelVoClass());

        //封装参数
        JSONObject jsonObject_para = JSONObject.parseObject(reportPanel.getParaData());
        if (jsonObject_para != null) {
            //封装查询开始时间
            result.setQueryStartTime(jsonObject_para.getInteger("queryStartTime"));
            String deviceType = jsonObject_para.getString("deviceType");
            //封装设备类型
            result.setDeviceType(deviceType);
            //封装查询机器人
            List<Long> deviceUniqueIdList = JSONObject.parseArray(jsonObject_para.getString("deviceUniqueIdList"), Long.class);
            result.setDeviceInfoList(this.listDeviceInfoByIds(reportPanel.getMerId(), deviceType, deviceUniqueIdList));
        }
        //封装显示字段
        JSONObject jsonObject_showData = JSONObject.parseObject(reportPanel.getShowData());
        if (jsonObject_showData != null) {
            //封装查询机器人
            List<String> showFieldList = JSONObject.parseArray(jsonObject_showData.getString("showFieldList"), String.class);
            result.setShowFieldList(showFieldList);
        }
        return result;
    }

    @Override
    public DataPanelVo getDataPanelById(Long id, Long merId) {
        ReportPanel reportPanel = dataPanelMapper.selectById(id, merId);

        if (reportPanel != null) {
            return convert(reportPanel);
        }
        return null;
    }

    @Override
    public void addDataPanel(DataPanelOptDto panelOptDto) {

        ReportPanel reportPanel = new ReportPanel();
        reportPanel.setId(IdWorker.getId());
        reportPanel.setMerId(panelOptDto.getMerId());
        reportPanel.setType(getDataPanelType().getId());
        reportPanel.setDeviceType(panelOptDto.getDeviceType());
        JSONObject para_data = new JSONObject();
        para_data.put("deviceType", panelOptDto.getDeviceType());
        para_data.put("deviceUniqueIdList", panelOptDto.getDeviceUniqueIdList());
        para_data.put("queryStartTime", panelOptDto.getQueryStartTime());
        reportPanel.setParaData(para_data.toJSONString());
        JSONObject show_data = new JSONObject();
        show_data.put("showFieldList", panelOptDto.getShowFieldList());
        reportPanel.setShowData(show_data.toJSONString());
        reportPanel.setRemark(panelOptDto.getRemark());
        int now = DateUtil.getNowTime();
        reportPanel.setCreateTime(now);
        reportPanel.setUpdateTime(now);

        dataPanelMapper.insertSelective(reportPanel);
    }

    @Override
    public void deleteDataPanel(DataPanelOptDto dataPanelOptDto) {

        if (Objects.isNull(dataPanelOptDto.getId()) || Objects.isNull(dataPanelOptDto.getMerId())) {
            throw new BusinessException("数据面板删除失败: 参数错误");
        }

        ReportPanel reportPanel = dataPanelMapper.selectById(dataPanelOptDto.getId(), dataPanelOptDto.getMerId());
        if (Objects.isNull(reportPanel)) {
            return;
        }
        //删除
        dataPanelMapper.deleteById(dataPanelOptDto.getId(), dataPanelOptDto.getMerId());
    }

    @Override
    public ReportPanel checkDataPanel(Long id, Long merId) {
        ReportPanel reportPanel = dataPanelMapper.selectById(id, merId);
        if (Objects.isNull(reportPanel)) {
            throw new BusinessException("数据面板不存在");
        }
        checkDataPanel(reportPanel);
        return reportPanel;
    }

    @Override
    public Boolean checkDataPanel(ReportPanel reportPanel) {

        JSONObject data;
        if (Objects.isNull(data = JSONObject.parseObject(reportPanel.getParaData()))) {
            throw new BusinessException("数据面板未设置查询条件数据");
        }

        //报表面板设备方案
        String deviceType = data.getString("deviceType");
        if (StringUtils.isBlank(deviceType)) {
            throw new BusinessException("数据面板未设置设备方案");
        }
        //报表面板机器人列表
        List<Long> deviceUniqueIdList = JSONObject.parseArray(data.getString("deviceUniqueIdList"), Long.class);
        if (ObjectUtils.isEmpty(deviceUniqueIdList)) {
            throw new BusinessException("数据面板未设置查询机器人");
        }
        //报表面板显示字段
        JSONObject showFieldJson = JSONObject.parseObject(reportPanel.getShowData());
        if (Objects.isNull(showFieldJson)) {
            throw new BusinessException("数据面板未设置显示字段数据");
        }
        //报表面板机器人
        List<String> showFieldList = JSONObject.parseArray(showFieldJson.getString("showFieldList"), String.class);
        if (ObjectUtils.isEmpty(showFieldList)) {
            throw new BusinessException("数据面板未设置显示字段");
        }
        //报表面板开始时间
        Integer queryStartTime = data.getInteger("queryStartTime");
        if (queryStartTime == null) {
            throw new BusinessException("数据面板未设置查询开始时间");
        }
        return true;
    }

    /**
     * 根据机器人查询设备信息
     *
     * @param merId              运营商id
     * @param deviceType         设备类型
     * @param deviceUniqueIdList 机器人id
     * @return list list
     */
    public List<DeviceInfoVo> listDeviceInfoByIds(Long merId, String deviceType, List<Long> deviceUniqueIdList) {
        if (ObjectUtils.isEmpty(deviceUniqueIdList)) {
            return Lists.newArrayList();
        }
        List<DeviceInfoVo> deviceInfoVoList = new ArrayList<>();
        for (Long deviceUniqueId : deviceUniqueIdList) {
            Device device = deviceService.findDeviceInfoByDeviceUniqueId(deviceUniqueId, deviceType, merId);
            if (device != null) {
                DeviceInfoVo deviceInfoVo = new DeviceInfoVo();
                BeanUtils.copyProperties(device, deviceInfoVo);
                Long groupId = device.getGroupId();
                DeviceGroup deviceGroup = deviceGroupMapper.selectById(groupId, device.getMerId());
                if (Objects.nonNull(deviceGroup)) {
                    deviceInfoVo.setGroupName(deviceGroup.getName());
                }
                deviceInfoVoList.add(deviceInfoVo);
            }
        }
        return deviceInfoVoList;
    }

    /**
     * Gets data panel type.
     *
     * @return the data panel type
     */
    public abstract ReportPanelTypeEnum getDataPanelType();

    /**
     * Child data panel vo class class.
     *
     * @return the class
     */
    public abstract Class<? extends DataPanelVo> childDataPanelVoClass();

    /**
     * remote数据查询
     *
     * @param query
     * @return
     */
    public abstract Object remoteDataQuery(DataPanelRemoteQuery query);

    /**
     * 修改数据面板
     *
     * @param editParam
     */
    public void editDataPanel(DataPanelOptDto editParam) {

        ReportPanel reportPanel = dataPanelMapper.selectById(editParam.getId(), editParam.getMerId());
        if (Objects.isNull(reportPanel)) {
            throw new BusinessException("数据面板不存在");
        }
        JSONObject paraDataObj = JSON.parseObject(reportPanel.getParaData());

        if (Objects.nonNull(editParam.getQueryStartTime())) {
            paraDataObj.put("queryStartTime", editParam.getQueryStartTime());
        }
        if (Objects.nonNull(editParam.getQueryEndTime())) {
            paraDataObj.put("queryEndTime", editParam.getQueryEndTime());
        }
        if (ObjectUtils.isNotEmpty(editParam.getDeviceUniqueIdList())) {
            paraDataObj.put("deviceUniqueIdList", editParam.getDeviceUniqueIdList());
        }
        if (ObjectUtils.isNotEmpty(editParam.getScenes())) {
            paraDataObj.put("scenes", editParam.getScenes());
        }
        if (ObjectUtils.isNotEmpty(editParam.getShowFieldList())) {
            JSONObject show_data = new JSONObject();
            show_data.put("showFieldList", editParam.getShowFieldList());
            reportPanel.setShowData(show_data.toJSONString());
        }

        reportPanel.setParaData(paraDataObj.toJSONString());
        reportPanel.setRemark(editParam.getRemark());
        reportPanel.setUpdateTime((int) (DateTime.now().getTime() / 1000));

        dataPanelMapper.updateByIdSelective(reportPanel);
    }

    /**
     * 检查remote参数
     *
     * @param query
     */
    public abstract Object checkAndBuildRemoteParam(DataPanelRemoteQuery query);

    public Object remark(Long id, String remark) {

        ReportPanel reportPanel = new ReportPanel();
        reportPanel.setId(id);
        reportPanel.setRemark(remark);
        return dataPanelMapper.updateByIdSelective(reportPanel);
    }
}
